package com.joelaws.prototype.server.dao;

import gnu.trove.TLongObjectHashMap;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.joelaws.prototype.client.data.Rating;
import com.joelaws.prototype.client.data.User;
import com.joelaws.prototype.client.util.Create;

public class RatingDAO {

	private TLongObjectHashMap<ArrayList<Rating>> fromCache;

	private TLongObjectHashMap<ArrayList<Rating>> toCache;

	protected RatingDAO() {
		fromCache = new TLongObjectHashMap<ArrayList<Rating>>();
		toCache = new TLongObjectHashMap<ArrayList<Rating>>();
	}

	public synchronized List<Rating> getFromRatings(User user) {
		return getFromRatings(user.getUserID());
	}

	public synchronized List<Rating> getFromRatings(long userID) {
		return fromCache.get(userID);
	}

	public synchronized Rating getRating(User fromUser, User toUser) {
		return getRating(fromUser.getUserID(), toUser.getUserID());
	}

	public synchronized Rating getRating(long fromUser, long toUser) {
		List<Rating> fromRatings = fromCache.get(fromUser);
		List<Rating> toRatings = toCache.get(toUser);
		if (fromRatings == null || toRatings == null) {
			return null;
		}
		Set<Rating> ratings = Create.newSet(fromRatings);
		ratings.retainAll(toRatings);

		if (ratings.size() > 1) {
			throw new RuntimeException("Should only have one rating between " + fromUser + " to " + toUser
					+ " but found " + ratings.size());
		}

		return ratings.iterator().next();
	}

	public synchronized List<Rating> getToRatings(User user) {
		return getToRatings(user.getUserID());
	}

	public synchronized List<Rating> getToRatings(long userID) {
		return toCache.get(userID);
	}

	public synchronized void store(Rating rating) {
		Rating other = this.getRating(rating.getRater(), rating.getRated());
		if (other != null) {
			other.setRating(rating.getRating());
			return;
		}

		ArrayList<Rating> ratings;

		ratings = fromCache.get(rating.getRater());
		if (ratings == null) {
			ratings = new ArrayList<Rating>();
		}
		ratings.add(rating);
		fromCache.put(rating.getRater(), ratings);

		ratings = toCache.get(rating.getRated());
		if (ratings == null) {
			ratings = new ArrayList<Rating>();
		}
		ratings.add(rating);
		toCache.put(rating.getRated(), ratings);

	}

	public synchronized void removeService(long userID) {
		fromCache.remove(userID);
	}
}
